package it.unibo.contact.convoyCruiseControlSystem;

import it.unibo.contact.platformuv.RunTimeKb;
import it.unibo.convoycruisecontrol.boatsubsystem.AbstractCommandBoat;
import it.unibo.convoycruisecontrol.boatsubsystem.DashboardManager;
import it.unibo.convoycruisecontrol.boatsubsystem.IBoatFactory;
import it.unibo.convoycruisecontrol.boatsubsystem.IDashboard;
import it.unibo.convoycruisecontrol.boatsubsystem.SendingNavigationInfo;
import it.unibo.convoycruisecontrol.boatsubsystem.SensingBoatStatus;
import it.unibo.convoycruisecontrol.chiefboatsubsystem.ControlPanel;
import it.unibo.convoycruisecontrol.chiefboatsubsystem.DistanceSupervisor;
import it.unibo.convoycruisecontrol.chiefboatsubsystem.IFlagDisplay;
import it.unibo.convoycruisecontrol.chiefboatsubsystem.IFlagDisplayFactory;
import it.unibo.convoycruisecontrol.chiefboatsubsystem.MapManager;
import it.unibo.convoycruisecontrol.chiefboatsubsystem.StatusSupervisor;
import it.unibo.convoycruisecontrol.chiefboatsubsystem.TimingSupervisor;
import it.unibo.convoycruisecontrol.simulation.Simulator;
import it.unibo.java.location.JavaLocationDeviceFactory;
import it.unibo.location.ILocationDeviceFactory;
import it.unibo.location.LocationDevice;
import it.unibo.mycruise.boat.BoatFactory;
import it.unibo.mycruise.boat.Dashboard;
import it.unibo.mycruise.boat.presentation.swing.DashboardFrame;
import it.unibo.mycruise.boat.presentation.swing.DashboardView;
import it.unibo.mycruise.chief.FlagDisplay;
import it.unibo.mycruise.chief.FlagDisplayFactory;
import it.unibo.mycruise.chief.presentation.swing.ChiefFrame;
import it.unibo.mycruise.chief.presentation.swing.ControlPanelController;
import it.unibo.mycruise.chief.presentation.swing.ControlPanelView;
import it.unibo.mycruise.chief.presentation.swing.FlagDisplayView;
import it.unibo.mycruise.simulation.SimulatorBoatFactory;
import it.unibo.mycruise.simulation.SimulatorControlPanel;
import it.unibo.mycruise.simulation.presentation.swing.SimulatorController;
import it.unibo.mycruise.simulation.presentation.swing.SimulatorFrame;
import it.unibo.mycruise.simulation.presentation.swing.SimulatorView;
import it.unibo.util.InformationConverter;
import it.unibo.util.PrologInformationConverter;

public class ConvoyCruiseControlSIMULATOR extends ConvoyCruiseControlSystemMain 
{
	static int N = 2;
	static int DT = 5000;
	static int DD = 1000;
	static int DMIN = 500;
	static int R = 2;
	static int a = 3;
	
	LocationDevice locDev;
	ILocationDeviceFactory locationDeviceFactory = new JavaLocationDeviceFactory();
	
	InformationConverter informationConverter = new PrologInformationConverter();

	//Boats
	IBoatFactory boatFactory = new SimulatorBoatFactory();
	AbstractCommandBoat[] boats;
	DashboardManager[] dashManagers;
	SendingNavigationInfo[] sendingNavInfo;
	SensingBoatStatus[] sensingBoatsStatus;
	DashboardView[] dashViews;
	
	//Simulator
	SimulatorView[] simViews;

	//Chief
	IFlagDisplayFactory flagDisplayFactory = new FlagDisplayFactory();
	MapManager _mapManager;
	SimulatorControlPanel _controlPanel;
	StatusSupervisor _statusSupervisor;
	IFlagDisplay _flagDisplay;
	DistanceSupervisor _distanceSupervisor;
	TimingSupervisor _timingSupervisor;
	ControlPanelView _controlPanelView;
	ControlPanelController _controlPanelController;
	ChiefFrame _chiefFrame;

	public static void main(String[] args) 
	{
		ConvoyCruiseControlSIMULATOR system = new ConvoyCruiseControlSIMULATOR();
		system.doJob();
	}

	@Override
	protected void configureSystem() 
	{
		RunTimeKb.init(view);
		//Protocols for application messages
			RunTimeKb.addSubject("TCP", "space","coreCmd", "localhost",8050);	
			RunTimeKb.addSubject("TCP", "space","outCmd", "localhost" ,8050);	
//			RunTimeKb.addSubject("TCP" , "statusSupervisor" , "enabled","localhost",8060 );   	
//			RunTimeKb.addSubject("TCP" , "mapManager" , "navigationInfo","localhost",8060 );   	
//			RunTimeKb.addSubject("TCP" , "distanceSupervisor" , "navigationInfo","localhost",8060 );   	
//			RunTimeKb.addSubject("TCP" , "startSupervisor" , "navigationInfo","localhost",8060 );   	
//			RunTimeKb.addSubject("TCP" , "timingSupervisor" , "navigationInfo","localhost",8060 ); 
//			RunTimeKb.addSubject("TCP" , "start" , "boat0","localhost",8070 ); 
//			RunTimeKb.addSubject("TCP" , "stop" , "boat0","localhost",8070 ); 
//			RunTimeKb.addSubject("TCP" , "start" , "boat1","localhost",8090 ); 
//			RunTimeKb.addSubject("TCP" , "stop" , "boat1","localhost",8090 ); 
		//Application messages
			RunTimeKb.addInputConnMsg( "coreCmd", true); //system request
		  		RunTimeKb.addInputConnMsg( "enabled", true);
		  		RunTimeKb.addInputConnMsg( "navigationInfo", true);
		  		RunTimeKb.addInputConnMsg( "start", true);
		  		RunTimeKb.addInputConnMsg( "stop", true);
	}

	@Override
	protected void start() 
	{
		for(int i = 0; i < N; i++)
		{
			boats[i].start();
			dashManagers[i].start();
			sendingNavInfo[i].start();
		}

		_mapManager.start();
		//		_controlPanel.start();
		_statusSupervisor.start();
		_distanceSupervisor.start();
		_timingSupervisor.start();
	}


	@Override
	protected void configureSubjects() 
	{
		locDev = locationDeviceFactory.createBestDevice();
		initBoatSubjects();
		initChiefSubjects();
	}

	private void initChiefSubjects()
	{
		try
		{
			// init components
			_mapManager = new MapManager(locDev, N, informationConverter);
			_mapManager.setName("mapManager");
			_mapManager.setEnv(null);
			_mapManager.initInputSupports();

			_controlPanel = new SimulatorControlPanel(N, DD, locDev, informationConverter);
			_controlPanel.setName("controlPanel");
			_controlPanel.setEnv(null);
			_controlPanel.initInputSupports();

			_flagDisplay = flagDisplayFactory.createFlagDisplay(N);

			_statusSupervisor = new StatusSupervisor((ControlPanel) _controlPanel, _flagDisplay, informationConverter);
			_statusSupervisor.setName("statusSupervisor");
			_statusSupervisor.setEnv(null);
			_statusSupervisor.initInputSupports();

			_distanceSupervisor = new DistanceSupervisor(DMIN, locDev, _controlPanel, informationConverter);
			_distanceSupervisor.setName("distanceSupervisor");
			_distanceSupervisor.setEnv(null);
			_distanceSupervisor.initInputSupports();

			_timingSupervisor = new TimingSupervisor(R*DT, _controlPanel, locDev, informationConverter);
			_timingSupervisor.setName("timingSupervisor");
			_timingSupervisor.setEnv(null);
			_timingSupervisor.initInputSupports();

			// init GUI
			_controlPanelController = new ControlPanelController(_controlPanel);
			_controlPanelView = new ControlPanelView(_controlPanelController);
			FlagDisplayView flagDisplayView = new FlagDisplayView((FlagDisplay) _flagDisplay);
			_chiefFrame = new ChiefFrame(_controlPanelView, flagDisplayView);

		}
		catch (Exception e) 
		{
			e.printStackTrace();
		}
	}


	private void initBoatSubjects()
	{
		try
		{
			boats = new AbstractCommandBoat[N];
			dashManagers = new DashboardManager[N];
			sendingNavInfo = new SendingNavigationInfo[N];
			sensingBoatsStatus = new SensingBoatStatus[N];
			dashViews = new DashboardView[N];
			simViews = new SimulatorView[N];

			for(int i = 0; i < N; i++)
			{
				// init components
				boats[i] = boatFactory.createBoat(locDev, i);
				boats[i].setName("boat"+i);
				boats[i].setEnv(null);
				boats[i].initInputSupports();

				IDashboard dash = boatFactory.createDashboard();
				dashManagers[i] = new DashboardManager(dash, boats[i].getNavigationInfo(), locDev, informationConverter);
				dashManagers[i].setName("dashboardManager");
				dashManagers[i].setEnv(null);
				dashManagers[i].initInputSupports();

				sendingNavInfo[i] = new SendingNavigationInfo(boats[i].getNavigationInfo(), informationConverter);
				sendingNavInfo[i].setName("sendingNavigationInfo");
				sendingNavInfo[i].setEnv(null);
				sendingNavInfo[i].initInputSupports();

				sensingBoatsStatus[i] = new SensingBoatStatus(informationConverter);
				sensingBoatsStatus[i].setName("sensingBoatStatus");
				sensingBoatsStatus[i].setEnv(null);
				sensingBoatsStatus[i].initInputSupports();

				boats[i].getStatusBoat().addBoatStatusListener(sensingBoatsStatus[i]);

				SimulatorController simController = new SimulatorController(new Simulator(boats[i]));
				
				// init GUI
				dashViews[i] = new DashboardView((Dashboard) dash);
				simViews[i] = new SimulatorView(simController);
				SimulatorFrame simFrame = new SimulatorFrame(simViews[i], dashViews[i]);
				
			}
		}
		catch (Exception e) 
		{
			e.printStackTrace();
		}
	}
}

